package vn.axonactive.devday.jsf.model;

import java.io.Serializable;
import java.text.DecimalFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collections;
import java.util.List;

import org.primefaces.model.chart.CartesianChartModel;
import org.primefaces.model.chart.LineChartSeries;



/**
 * Represent a stock quote entity. It contains some necessary data of a specific share such as its symbol, price... 
 *  
 */
public class StockQuote implements Serializable{
	
	private static final long serialVersionUID = -3981973710754584039L; 
	private static final DecimalFormat DECIMAL_FORMAT = new DecimalFormat("#.#");
	private int maxChartValue = 0;
	
	/**
	 * Hold the changing direction of a share price. It could be DOWN, UP or UNCHANGED. 
	 *
	 */
	public enum PriceChangeDirection
	{
		/**
		 * if current price is the same as previous day's closing value
		 */
		UNCHANGED,
		/**
		 * if current price is higher than previous day's closing value
		 */
		UP,
		/**
		 * 
		 * if current price is lower than previous day's closing value 
		 */
		DOWN
	}
	
	/**
	 * The one to four letter code that presents a particular share
	 */
	private String symbol;
	
	/**
	 * Listing company name.
	 */
	private String companyName;
	
	/**
	 * The price of a particular share
	 */
	private double currentPrice;
	
	/**
	 * The total number of shares traded for the day.
	 */
	private int volume;
	
	/**
	 * The price that someone has offered to pay for the share.
	 */
	private double bidPrice;
	
	/**
	 * The price at which a holder of a stock is willing to sell the share.
	 */
	private double askPrice;
	
	/**
	 * The price which was paid for the first shares of stock traded on the current trading day.
	 */
	private double openPrice;
	
	/**
	 * The price of the stock at the close of the previous trading day. 
	 */
	private double previousClose;
	
	/**
	 * The history of price and volume of this stock
	 */
	private List<StockQuoteHistory> history = new ArrayList<StockQuoteHistory>();
	
	/**
	 * Contains the previous prices  
	 */
	
	public String getSymbol()
	{
		return symbol;
	}

	public void setSymbol(String symbol)
	{
		this.symbol = symbol;
	}

	public String getCompanyName()
	{
		return companyName;
	}

	public void setCompanyName(String companyName)
	{
		this.companyName = companyName;
	}

	public double getCurrentPrice()
	{
		return currentPrice;
	}

	public void setCurrentPrice(double currentPrice)
	{
		this.currentPrice = currentPrice;
	}

	public int getVolume()
	{
		return volume;
	}

	public void setVolume(int volume)
	{
		this.volume = volume;
	}

	public double getBidPrice()
	{
		return bidPrice;
	}

	public void setBidPrice(double bidPrice)
	{
		this.bidPrice = bidPrice;
	}

	public double getAskPrice()
	{
		return askPrice;
	}

	public void setAskPrice(double askPrice)
	{
		this.askPrice = askPrice;
	}

	public double getOpenPrice()
	{
		return openPrice;
	}

	public void setOpenPrice(double openPrice)
	{
		this.openPrice = openPrice;
	}

	public double getPreviousClose()
	{
		return previousClose;
	}

	public void setPreviousClose(double previousClose)
	{
		this.previousClose = previousClose;
	}
	
	
	/**
	 * Return the changing direction of the share price. If current price is higher than previous closed price, means the price of share has gone up and vice versa.
	 *  
	 * @return {@link PriceChangeDirection}
	 */
	public PriceChangeDirection getPriceChangeDirection()
	{
		if (currentPrice > previousClose)
		{
			return PriceChangeDirection.UP;
		}
		if (currentPrice < previousClose)
		{
			return PriceChangeDirection.DOWN;
		}
		return PriceChangeDirection.UNCHANGED;
	}

	
	/**
	 * The percent of net price changed from previous day's close.
	 * <br><br> For example: If the share of HAG has current price is 103.000 VND while its previous closed price was 100.000 VND. Then the percent of changing in price is (103.000VND-100.000VND)*100/100.000VND = 3%.  
	 * 
	 * @return percent of changed price
	 */
	public double getPercentOfChange() {
		if (currentPrice > previousClose)
		{
			return Double.valueOf(DECIMAL_FORMAT.format((currentPrice-previousClose)*100/previousClose));
		}
		return Double.valueOf(DECIMAL_FORMAT.format((previousClose-currentPrice)*100/currentPrice));
	}


	public void createHistoryEntry(StockQuote sq){
		Calendar c = Calendar.getInstance();
		c.add(Calendar.DATE, (history.size()+1)*-1);  
		history.add(new StockQuoteHistory(c, sq.currentPrice, sq.volume));
	}

	public List<StockQuoteHistory> getHistory() {
		return history;
	}
	
	public void clearHistory(){
		history.clear();
	}

	public CartesianChartModel getHistoryModel(){
		SimpleDateFormat DATE_FORMAT = new SimpleDateFormat("dd.MMM.yyyy hh:mm:ss");
		CartesianChartModel linearModel = new CartesianChartModel();
		ArrayList<Integer> arrayList = new ArrayList<Integer>();
		
		LineChartSeries prices = new LineChartSeries();
		LineChartSeries volumes = new LineChartSeries();
		
		prices.setLabel("price");
		volumes.setLabel("volume (10k)");
		for(StockQuoteHistory sqh:getHistory()){
	        String date = DATE_FORMAT.format(sqh.getCalendar().getTime());
	        //to get high value
	        arrayList.add(sqh.getVolume()/1000);
	        arrayList.add((int) sqh.getPrice());
			volumes.set(date, (sqh.getVolume()/1000));
			prices.set(date, sqh.getPrice());
		}
		maxChartValue = Collections.max(arrayList);
		linearModel.addSeries(prices);
		linearModel.addSeries(volumes);
		return linearModel; 
	}
	
	public int getMaxChartValue(){
		return maxChartValue+20;
	}
}
